<script setup lang="ts">
import {computed, onMounted, onUnmounted, ref, watch} from 'vue'
import type{ TooltipProps, TooltipEmits,TooltipInstance} from './type';
import{  createPopper,  type Instance } from '@popperjs/core';
import { debounce } from 'lodash-es';
// 点击外侧恢复的 工具
import useClickOutside from '@/hooks/useClickOutside';

// 设置默认值

const props = withDefaults(defineProps<TooltipProps>(),{
  placement:'bottom',
  trigger:'click',
  // transition:'fade'
})

const emit = defineEmits<TooltipEmits>()

// 实现 popper 参数
const prpOption = computed(()=>{
  return {
    placement:props.placement,
    ...props.popperOptions
  }
})

// 控制显示标记
const isOpen = ref<boolean>(false)

// 创建两个dom 对象，进行tooltip 的效果
const popperContainerNode = ref<HTMLElement>() // 用于后面一个 bug 修复 和 点击外侧 用。
const triggerNode = ref<HTMLElement>()
const popperNode = ref<HTMLElement>()
// Tooltip 实例，用于 手动控制的功能。
let popperInstance:Instance | null = null

// 点击事件 --切换open(取反)
const handleClick = ()=>{
  isOpen.value = !isOpen.value
  emit('visible-change',isOpen.value)
}

// 延时显示功能
const delayTime = ref(1000)
// open / close
const open = ()=>{
    isOpen.value = true
    // 通知外部
    emit('visible-change',isOpen.value)
  }
const close = ()=>{
    isOpen.value = false
    // 通知外部
    emit('visible-change',isOpen.value)
  }

const openDebounce = debounce(open,delayTime.value)
const closeDebounce = debounce(close,delayTime.value)

const openFinal = ()=>{
  closeDebounce.cancel()
  openDebounce()
}

const closeFinal = ()=>{
  openDebounce.cancel()
  closeDebounce()
}
// 处理点击外侧
useClickOutside(popperContainerNode,()=>{
  if(props.trigger === 'click' && isOpen.value && !props.manual){
    close()
  }
  // 点击外侧
  if(isOpen.value){
    emit('click-outside',true)
  }
})

// 显示 或 隐藏的同时 需要创建或销毁 tooltip

watch(isOpen,
(newValue)=>{
  if(newValue){
    if(triggerNode.value && popperNode.value){
      // 节点存在，且open为true，显示--> 创建实例
      console.log('创建实例了')
      popperInstance = createPopper(triggerNode.value,popperNode.value,prpOption.value)
    }
  }
  else{
    // 销毁
    if(popperInstance){
      popperInstance.destroy()
      console.log('销毁实例了')
    }
  }
},
{
  flush:'post'
})

// 事件对象(响应式的)
const event  = ref<Record<string,any>>({})
const outevent  = ref<Record<string,any>>({})

//动态添加事件
const attachEvent = ()=>{
  if(props.trigger==='click'){
    event.value['click'] = handleClick
  }
  else if(props.trigger==='hover'){
    event.value['mouseenter'] = openFinal
    outevent.value['mouseleave'] = closeFinal
  }
}

// 没有手动触发才动态添加事件
if(!props.manual){
  attachEvent()
}
watch(()=>props.manual,(isManual)=>{
  if(isManual){
    event.value = {}
    outevent.value = {}
  }
  else{
    attachEvent()
  }
})

onMounted(()=>{
  attachEvent()
})

// 如果动态修改了 trigger,需要重新添加事件
watch(()=>props.trigger,(newVal)=>{
  // 既然变化了，就重新加载一遍事件。不管trigger是什么。
  if(!props.manual){
    event.value = {}
    outevent.value = {}
    attachEvent()
  }
})

// Tooltip 实例向外暴露的 方法
defineExpose<TooltipInstance>({
  show:open,
  hide:close,
})

// 页面销毁需要销毁popper实例
onUnmounted(()=>{
  popperInstance?.destroy()
})

</script>
<template>
  <div class="wf-tooltip" v-on="outevent" ref="popperContainerNode">
    <!-- 触发节点 -->
    <div class="wf-tooltip__trigger"  v-on="event" ref="triggerNode">
      <!-- 默认插槽 -->
      <slot></slot>
    </div>
    <!-- 展示节点 -->
    <!-- <Transition :name="transition"> -->
    <div class="wf-tooltip__popper" v-if="isOpen" ref="popperNode">
      <slot name="content"><span>{{ content }}</span></slot>
    </div>
    <!-- </Transition> -->
    
  </div>
</template>
